﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Text;

namespace Apewer.Source
{

    /// <summary>数据库客户端。</summary>
    public interface IDbAdo : IDisposable
    {

        /// <summary>允许 ADO 抛出异常，取代返回错误信息。</summary>
        /// <value>FALSE（默认值）</value>
        bool ThrowAdoException { get; set; }

        #region Connection

        /// <summary>获取连接。</summary>
        IDbConnection Connection { get; }

        /// <summary>获取连接字符串。</summary>
        string ConnectionString { get; }

        /// <summary>数据库当前在线，表示连接可用。</summary>
        bool Online { get; }

        /// <summary>关闭连接后，执行的方法。</summary>
        Action<IDbAdo> OnClosed { get; set; }

        /// <summary>连接数据库，若未连接则尝试连接，返回错误信息。</summary>
        string Connect();

        /// <summary>更改已打开的数据库。</summary>
        string Change(string store);

        /// <summary>关闭连接，并释放对象所占用的系统资源。</summary>
        void Close();

        #endregion

        #region ADO

        /// <summary>查询。</summary>
        IQuery Query(string sql, IEnumerable<IDataParameter> parameters = null);

        /// <summary>执行。</summary>
        IExecute Execute(string sql, IEnumerable<IDataParameter> parameters = null, bool autoTransaction = false);

        /// <summary>创建参数。</summary>
        /// <exception cref="ArgumentNullException"></exception>
        IDataParameter Parameter(string name, object value);

        /// <summary>创建参数。</summary>
        /// <exception cref="ArgumentNullException"></exception>
        IDataParameter Parameter(string name, object value, DbType type);

        #endregion

        #region Transaction

        /// <summary>获取已启动的事务。</summary>
        IDbTransaction Transaction { get; }

        /// <summary>
        /// <para>使用默认的事务锁定行为启动事务。</para>
        /// <para>Chaos<br />无法覆盖隔离级别更高的事务中的挂起的更改。</para>
        /// <para>ReadCommitted<br />在正在读取数据时保持共享锁，以避免脏读，但是在事务结束之前可以更改数据，从而导致不可重复的读取或幻像数据。</para>
        /// <para>ReadUncommitted<br />可以进行脏读，意思是说，不发布共享锁，也不接受独占锁。</para>
        /// <para>RepeatableRead<br />在查询中使用的所有数据上放置锁，以防止其他用户更新这些数据。 防止不可重复的读取，但是仍可以有幻像行。</para>
        /// <para>Serializable<br />在 System.Data.DataSet 上放置范围锁，以防止在事务完成之前由其他用户更新行或向数据集中插入行。</para>
        /// <para>Snapshot<br />通过在一个应用程序正在修改数据时存储另一个应用程序可以读取的相同数据版本来减少阻止。 表示您无法从一个事务中看到在其他事务中进行的更改，即便重新查询也是如此。</para>
        /// <para>Unspecified = -1<br />正在使用与指定隔离级别不同的隔离级别，但是无法确定该级别。</para>
        /// </summary>
        /// <param name="commit">在连接的生命周期结束时未结束事务，指定 TRUE 将自动提交，指定 FALSE 将自动回滚。</param>
        string Begin(bool commit = false);

        /// <summary>
        /// <para>使用指定的事务锁定行为启动事务。</para>
        /// <para>Chaos<br />无法覆盖隔离级别更高的事务中的挂起的更改。</para>
        /// <para>ReadCommitted<br />在正在读取数据时保持共享锁，以避免脏读，但是在事务结束之前可以更改数据，从而导致不可重复的读取或幻像数据。</para>
        /// <para>ReadUncommitted<br />可以进行脏读，意思是说，不发布共享锁，也不接受独占锁。</para>
        /// <para>RepeatableRead<br />在查询中使用的所有数据上放置锁，以防止其他用户更新这些数据。 防止不可重复的读取，但是仍可以有幻像行。</para>
        /// <para>Serializable<br />在 System.Data.DataSet 上放置范围锁，以防止在事务完成之前由其他用户更新行或向数据集中插入行。</para>
        /// <para>Snapshot<br />通过在一个应用程序正在修改数据时存储另一个应用程序可以读取的相同数据版本来减少阻止。 表示您无法从一个事务中看到在其他事务中进行的更改，即便重新查询也是如此。</para>
        /// <para>Unspecified = -1<br />正在使用与指定隔离级别不同的隔离级别，但是无法确定该级别。</para>
        /// </summary>
        /// <param name="commit">在连接的生命周期结束时未结束事务，指定 TRUE 将自动提交，指定 FALSE 将自动回滚。</param>
        /// <param name="isolation">指定事务锁定行为，不指定时将使用默认值。</param>
        string Begin(bool commit, IsolationLevel isolation);

        /// <summary>提交事务。</summary>
        /// <remarks>异常常见于事务已经提交或连接已断开。</remarks>
        /// <returns>提交失败时返回错误信息，成功时返回 NULL 值。</returns>
        string Commit();

        /// <summary>从挂起状态回滚事务。</summary>
        /// <remarks>异常常见于事务已经提交、已回滚或连接已断开。</remarks>
        /// <returns>提交失败时返回错误信息，成功时返回 NULL 值。</returns>
        string Rollback();

        #endregion

    }

}
